home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 288_01.zip / SD.C < prev    next >
Text File  |  1993-04-01  |  10KB  |  428 lines

  1. /*
  2. HEADER:        ;
  3. TITLE:        Enhaced Chdir command;
  4. VERSION:    1.2;
  5.  
  6. DESCRIPTION:    "
  7.  
  8.     SD (Set Directory): this is a replacement for the MS-DOS
  9.     CD (Chdir: change directory) command.
  10.  
  11.     SD is upwardly compatible with CD, all options of the CD command
  12.     have been implemented in SD. The only exception is that
  13.     
  14.         SD <drive:><path> 
  15.         
  16.     will switch to the specified drive.
  17.     
  18.     Extended options:    
  19.     
  20.     SD ? or SD /?   Gives a usage (help) message
  21.  
  22.     SD -            Returns to the last directory used (by SD)
  23.             This makes use of the MS-DOS environment to
  24.             keep the name of the last path in #SD_LAST.
  25.  
  26.     SD [<drive>:]path       This sets a new drive and path. If no
  27.                 drive is given the current drive is used.
  28.  
  29.     SD <name>       The file SD.DAT, in a directory specified by PATH
  30.             is used to store a list of logical names, and the
  31.             drive & path associated with the name.
  32.             
  33.             V1.1 Added ability to invoke a program after 
  34.             moving to the directory.
  35.             
  36.             BDF Aug. 88
  37.             
  38.             eg:
  39.  
  40.             123     c:\123 123 
  41.             pas     c:\dev\pas
  42.             c       c:\dev\c
  43.  
  44.             Thus the command line:
  45.             
  46.                 SD C
  47.                 
  48.             Will move you to drive C, path \DEV\C. While
  49.             
  50.                 SD 123
  51.                 
  52.             Will move to drive C, path \123 and start the
  53.             program 123.
  54.  
  55.     History:
  56.  
  57.     V1.1    Added abilty to start a program after moving to a named
  58.         logical directory.
  59.  
  60.         BDF Aug. 1988
  61.  
  62.     V1.2    Stored the name of the last path used in the environment
  63.         variable SDLAST. This was the original intention but I
  64.         could not find a way to do it, so I used a temp. file to
  65.         hold the name of the last path. However, a back issue of
  66.         Micro Cornucopia (issue 42) I found in a shop, contained
  67.         an articule by Scott Robert Ladd on how to do it (see
  68.         GLOBENV.C). Thank you Scott.
  69.             
  70.         BDF Jan. 1989";
  71.  
  72. FILENAME:    SD.C;
  73. WARNINGS:    ;
  74. SEE-ALSO:    ;
  75. AUTHORS:    Brian Farquhar (with thanks to Scott Robert Ladd);
  76. COMPILERS:    Microsoft C v5.1 & QuickC;
  77.             
  78. */
  79. #include <stdlib.h>
  80. #include <stdio.h>
  81. #include <ctype.h>
  82. #include <string.h>
  83. #include <direct.h>
  84. #include <process.h>
  85. #include <dos.h>
  86.  
  87. #define TRUE        1            /* Logical true        */
  88. #define FALSE           0            /* Logical false    */
  89. #define MATCH        0            /* Match on strcmp()    */
  90. #define EOL        '\n'            /* End of line char    */
  91. #define MAX_LINE        255            /* Data file Max. line    */
  92. #define CDERROR         -1                      /* Error from chdir()   */
  93. #define DATAFILE    "SD.DAT"        /* Logical names file    */
  94. #define LASTPATH    "SDLAST"        /* Last path         */
  95. #define DELIMITERS    " \t"            /* Used in strtok()    */
  96.  
  97. extern char *getgenv(char *varname);
  98. extern int   putgenv(char *varname, char *vartext);
  99. extern int   delgenv(char *varname);
  100.  
  101. /*    Local functions        */
  102.  
  103. void help_msg(void);
  104. void prt_cwd(void);
  105. void set_path(char *path);
  106. void save_path(void);
  107. char *get_last(char *path);
  108. void prt_path(char drive);
  109. int  logical_name(char *name);
  110. void search_path(char *file, char *path);
  111.  
  112. void    main(    int     argc,
  113.         char    **argv)
  114. {
  115.     char    path[_MAX_PATH];        /* directory path    */
  116.     char    *path_ptr;
  117.  
  118.     if (argc == 1)    /* asking for the current path? (SD <cr>)    */
  119.     {    
  120.         prt_cwd();        /* print the current path    */
  121.         
  122.         printf("\nLast path\t= %s",get_last(path));
  123.         printf("\n\nUse the '/?' option for help.\n",argv[0]);
  124.     }
  125.     
  126.     /* Asking for the path on another drive? (SD <drive>:)  */
  127.     
  128.     else if (strlen(argv[1]) == 2 && argv[1][1] == ':')
  129.     {
  130.         prt_path(argv[1][0]);        /* path on drive x    */
  131.         printf("\nLast path\t= %s\n",get_last(path));
  132.     }
  133.         
  134.     /*      did he ask for help? (SD ? or SD /?)   */
  135.  
  136.     else if (argv[1][0] == '?'|| (strcmp(argv[1],"/?") == MATCH))
  137.  
  138.         help_msg();
  139.  
  140.     /*      go back to the last directory? (SD -)   */
  141.  
  142.     else if (strcmp(argv[1],"-") == MATCH)
  143.     {    
  144.         path_ptr    = get_last(path);
  145.         save_path();
  146.         set_path(path_ptr);
  147.     }
  148.     
  149.     else        /* try to set the given path    */
  150.     {
  151.         save_path();        /* save the current path    */
  152.         
  153.         if (!logical_name(argv[1]))
  154.             set_path(argv[1]);
  155.     }
  156.  
  157.     exit(0);
  158. }
  159.  
  160. /************************************************************************
  161.  
  162.     Test to see if the "name" is a logical name in the datafile.
  163. If it is, return a value of TRUE after moving to the associated directory
  164. path. Otherwise return FALSE.
  165.  
  166. V1.1    Added ability to invoke the program named in the data file.
  167.  
  168. ************************************************************************/
  169.  
  170. int    logical_name(    char    *name)
  171. {
  172.     char    file[_MAX_PATH];    /* full file spec of DATAFILE    */
  173.     char    buff[MAX_LINE];        /* line from the DATAFILE    */
  174.     char    *token;
  175.     FILE    *fp;            /* file pointer for DATAFILE    */
  176.     char    *prog;            /* program to chain to        */
  177.     int    c;
  178.     int    i;
  179.                         
  180.     search_path(DATAFILE,file);    /* look for the file on PATH    */
  181.  
  182.     if (file[0] == NULL)        /* found it?            */
  183.     {
  184.         printf("Error: can not find the data file '%s'.",DATAFILE);
  185.         return(FALSE);
  186.     }
  187.     
  188.     if ((fp = fopen(file,"r")) == NULL)    /* open the data file    */
  189.     {
  190.         printf("\nError: unable to open the file '%s'.\n",file);
  191.         return(FALSE);
  192.     }
  193.  
  194.     i    = 0;
  195.     
  196.     while ((c = fgetc(fp)) != EOF)        /* read the data file    */
  197.     {
  198.         if (i == MAX_LINE -1)        /* line too long?    */
  199.         {
  200.             fprintf(stderr,"Maximum of %d characters per line"
  201.                     " in '%s'.",MAX_LINE,DATAFILE);
  202.             c    = EOL;
  203.         }
  204.         
  205.         if (c == EOL)
  206.         {
  207.             /*    Now we have a line from the data file,
  208.                 use the strtok() function to get the
  209.                 logical name on the line, and if it is
  210.                 the required name move to the directory
  211.                 given by the second token.
  212.                 
  213.                 V1.1 If a third token is on the line try
  214.                 and invoke it as a program.
  215.             */
  216.             
  217.             buff[i]    = '\0';
  218.             i    = 0;
  219.             token    = strtok(buff,DELIMITERS);
  220.  
  221.             if (strcmp(token,name) == MATCH) 
  222.             {
  223.                 /* get the next token    */
  224.                 
  225.                 token    = strtok(NULL,DELIMITERS);
  226.                 set_path(token);
  227.  
  228.                 prog    = strtok(NULL,DELIMITERS);
  229.  
  230.                 if (prog != NULL)
  231.                     system(prog);
  232.                     
  233.                 return(TRUE);
  234.             }
  235.         }
  236.         else
  237.         {
  238.             buff[i]    = (char) c;
  239.             i++;
  240.         }
  241.     }
  242.  
  243.     return(FALSE);
  244. }            
  245.  
  246. /************************************************************************
  247.  
  248.     print a help (usage) message.
  249.  
  250. ************************************************************************/
  251.  
  252. void    help_msg(void)
  253. {
  254.     printf( "\nSD: Set Directory, an enhanced Chdir command\n"
  255.         "\nSD version 1.1:"
  256.         "\tAdded ability to call a program\n"
  257.         "\t\t\twhen moving to a named directory\n"
  258.         "\nUsage:\tSD <CR>\t"
  259.         "\tWith no parameters prints the current path\n"
  260.         "\tSD <drive>:\tPrints the current path on the given drive\n"
  261.         "\tSD /? \t\tPrints this help message\n"
  262.         "\tSD - \t\tReturns to the last directory used (by SD)\n"
  263.         "\tSD [d:]path\tSet the path to the given drive and path\n"
  264.         "\tSD <name> \tMove to the directory in the file SD.DAT\n");
  265. }
  266.  
  267. /************************************************************************
  268.  
  269.     Print the C(urrent) W(orking) D(irectory)
  270.  
  271. ************************************************************************/
  272.  
  273. void    prt_cwd(void)
  274. {
  275.     char    path[_MAX_PATH];
  276.  
  277.     if (getcwd(path,_MAX_PATH) == NULL)
  278.         perror("Get current working directory error");
  279.     else
  280.         printf("\nPath on %c:\t= %s",path[0],path);
  281. }
  282.  
  283. /************************************************************************
  284.  
  285.     set the given drive (optional) & path
  286.  
  287. ************************************************************************/
  288.  
  289. void    set_path(char *path)
  290. {
  291.     unsigned        curr_drive;
  292.     unsigned        num_drives;
  293.     unsigned    tmp,i;
  294.     
  295.     if (isalpha(path[0]) && path[1] == ':')        /* drive given?    */
  296.     {
  297.         i    = toupper(path[0]) - 'A' + 1;    /* A=0, B=1...    */
  298.         tmp    = i;
  299.     
  300.         _dos_getdrive(&curr_drive);
  301.         _dos_setdrive(tmp,&num_drives);
  302.         
  303.         /*      validate the drive      */
  304.         
  305.         _dos_getdrive(&tmp);
  306.         
  307.         if (tmp != i)
  308.         {
  309.             if (tmp != curr_drive)
  310.                 _dos_setdrive(curr_drive,&num_drives);
  311.         
  312.             exit(1);
  313.         }
  314.     }
  315.     
  316.     if (chdir(path) == CDERROR)
  317.     {
  318.         printf("Error changing to '%s'.\n",path);
  319.         exit(-1);
  320.     }    
  321. }
  322.  
  323. /************************************************************************
  324.  
  325.     Save the current path.
  326.  
  327. ************************************************************************/
  328.  
  329. void    save_path(void)
  330. {
  331.     char    path[_MAX_PATH];    /* current path to save        */
  332.  
  333.     if (getcwd(path,_MAX_PATH) == NULL)
  334.     {
  335.         perror("Get current working directory error");
  336.         exit(-1);
  337.     }
  338.     
  339.     if (putgenv(LASTPATH,path) != 0)
  340.     {
  341.         printf("Error saving the path in the environment table.");
  342.         exit(-1);
  343.     }
  344. }
  345.  
  346. /************************************************************************
  347.  
  348.     Get the last path from the LASTPATH environment variable.
  349.  
  350. ************************************************************************/
  351.  
  352. char    *get_last(char *path)
  353. {
  354.     path    = getenv(LASTPATH);
  355.     return(path);
  356. }
  357.  
  358. /************************************************************************
  359.  
  360.     Get and display the path on another drive, and the last path
  361.  
  362. ************************************************************************/
  363.  
  364. void    prt_path(char drive)
  365. {
  366.     void prt_cwd(void);
  367.  
  368.     unsigned    curr_drive;    /* current drive         */
  369.     unsigned    tmp;        /* temp. drive            */
  370.     unsigned        num_drives;     /* highest drive No.            */
  371.     unsigned    i;
  372.     
  373.     tmp     = toupper(drive) - 'A' + 1;
  374.     i    = tmp;
  375.     
  376.     _dos_getdrive(&curr_drive);
  377.     _dos_setdrive(tmp,&num_drives);
  378.  
  379.     /*      validate the drive      */
  380.  
  381.     _dos_getdrive(&tmp);
  382.  
  383.     if (tmp != i)
  384.     {
  385.         if (tmp != curr_drive)
  386.             _dos_setdrive(curr_drive,&num_drives);
  387.  
  388.         exit(-1);
  389.     }
  390.  
  391.     prt_cwd();              /* Print path on current drive    */
  392.     
  393.     _dos_setdrive(curr_drive,&num_drives);    /* re-set the old drive    */
  394. }
  395.  
  396. /************************************************************************
  397.  
  398.     There is a bug in the _searchenv function (I think). If the file
  399. you are looking for is in the current working directory, and that is the
  400. root for that drive, the funtion adds an extra "\".
  401.  
  402. e.g.    E:\\SDLAST.PTH not E:\SDLAST.PTH.
  403.  
  404.     This routine traps the bug.
  405.  
  406. ************************************************************************/
  407.  
  408. void search_path(char     *file,        /* the file to search for    */
  409.          char    *path)        /* the path returned        */
  410. {
  411.     int     i;
  412.  
  413.     _searchenv(file,"PATH",path);
  414.     
  415.     if (strlen(path) > 3)        /* check for the \\ error    */
  416.     {
  417.         if (path[2] == '\\' && path[3] == '\\')
  418.         {
  419.             /* found the "\\" so shift everything 1 left    */
  420.             
  421.             for (i = 3; i < strlen(path) - 1; i++)
  422.                 path[i] = path[i+1];
  423.  
  424.             path[i] = '\0';
  425.         }
  426.     }
  427. }
  428.